package com.shiyi.system.aop;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mysql.cj.util.StringUtils;
import com.shiyi.core.vo.TokenUser;
import com.shiyi.system.annotation.OperaLog;
import com.shiyi.system.entity.OperationLog;
import com.shiyi.system.entity.SysUser;
import com.shiyi.system.service.OperationLogService;
import com.shiyi.system.service.SysUserService;
import com.shiyi.system.utils.UserManager;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author shiyi
 * @version 1.0
 * @date 2020-12-8 10:53
 */
@Aspect
@Component
public class OperationLogAop {

    @Autowired
    private UserManager userManager;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private OperationLogService operationLogService;

    private  final Logger logger = LoggerFactory.getLogger(OperationLogAop.class);


    @Pointcut("@annotation(com.shiyi.system.annotation.OperaLog)")
    public void logPoint() {}

    @AfterReturning(value = "logPoint()", returning = "keys")
    public void saveLog(JoinPoint joinPoint, Object keys) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert requestAttributes != null;
        HttpServletRequest request = requestAttributes.getRequest();
        // 获取切入点的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        OperaLog operaLog = method.getAnnotation(OperaLog.class);
        // 获取操作内容
        OperationLog log = getOperationContent(request, operaLog, joinPoint, keys, method);
        operationLogService.save(log);
        logger.warn(log.toString());
    }

    /**
     * 操作内容
     */
    private OperationLog getOperationContent(HttpServletRequest request, OperaLog operaLog, JoinPoint joinPoint, Object keys, Method method) {
        // 获取参数信息
        String parm = "";
        // 请求返回的结果
        String result = JSON.toJSONString(keys);
        String name = "";
        String realName = "";
        // ip地址
        String addr = request.getRemoteAddr();
        // ua
        String ua = request.getHeader("User-Agent");
        // 模块
        String module = operaLog.operaModule();
        int type = operaLog.type();
        // 新增，修改，删除
        if (type == 1 || type == 2 || type == 3) {
            // 操作人
            TokenUser userByToken = userManager.getUserByToken(request);
            name = userByToken.getUserName();
            realName = userByToken.getRealName();
            if (type == 1 || type == 2) {
                parm = JSON.parseObject(JSONObject.toJSONString(joinPoint.getArgs()[0])).toJSONString();
            }
            if (type == 3) {
                parm = (String) joinPoint.getArgs()[0];
            }
        } else if (type == 4){
            // 登录
            name = (String) joinPoint.getArgs()[0];
            if (!StringUtils.isNullOrEmpty(name)) {
                SysUser sysUser = sysUserService.queryUserByName(name);
                if (sysUser != null) {
                    realName = sysUser.getRealName();
                }
            }
            parm = (String) joinPoint.getArgs()[0];
            // 退出登录
        } else if (type == 5) {
            TokenUser userByToken = userManager.getUserByToken(request);
            name = userByToken.getUserName();
            realName = userByToken.getRealName();
            userManager.loginOutUser(request);
        }
        String content = "参数:" + parm + "-返回的结果:" + result;
        return new OperationLog(name, realName, addr, ua, type, module, content, new Date(), null);
    }


    private Map<String, String> converMap(Map<String, String[]> parameterMap) {
        Map<String, String> map = new HashMap<>();
        if (parameterMap != null && parameterMap.size() > 0) {
            for (String key : parameterMap.keySet()) {
                map.put(key, parameterMap.get(key)[0]);
            }
        }
        return map;
    }
}
